package me.youline.dataServer.service.pubMsg;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

import me.youline.dataServer.dao.PubMsgDAO;
import me.youline.dataServer.dao.PubMsgIndexDAO;
import me.youline.dataServer.dao.PubMsgStatisticRecorderDAO;
import me.youline.dataServer.entity.PubMsgStatisticRecorder;
import me.youline.dataServer.entity.PublicMessage;
import me.youline.dataServer.entity.PublicMessage.MsgStatus;
import me.youline.dataServer.entity.PublicMessageIndex;
import me.youline.dataServer.exception.ImageScaleException;
import me.youline.dataServer.exception.PubMsgServiceException;
import me.youline.dataServer.service.image.ImageScaleService;
import me.youline.dataServer.service.image.RatioImageScaleContext;
import me.youline.dataServer.service.support.file.FileBuilder.FileEntity;
import me.youline.dataServer.service.support.file.FileLocationConfig;
import me.youline.dataServer.service.support.file.FileLocatorManager;

import org.perf4j.aop.Profiled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 公告创建业务类，负责执行公告数据持久化，及相关资源文件的存储
 * @author linhan
 *
 */
@Component
public class PubMsgBuildService {

	@Autowired
	private PubMsgIndexDAO publicMessageIndexDAO;

	@Autowired
	private PubMsgDAO pubMsgDAO;

	@Autowired
	private ImageScaleService scaleService;

	@Autowired
	private PubMsgStatisticRecorderDAO msgRecorderDAO;
	
	@Autowired
	private FileLocatorManager fileLocatorManager;

	/**
	 * 发布公告消息，包括仅自己可见的信息
	 * 
	 * @param creatorId
	 * @param dto
	 * @param picEntity
	 * @param arContentEntity
	 * @return
	 * @throws ImageScaleException
	 * @throws IOException
	 * @throws PubMsgServiceException
	 */
	@Transactional(rollbackFor = Exception.class)
	@Profiled(tag = "service-创建原创消息", logFailuresSeparately = true)
	public PublicMessage buildOriginalPublicMessage(PubMsgBuildContext ctx)
			throws IOException, ImageScaleException {
		PubMsgBuildContextWrapper wrapper = new PubMsgBuildContextWrapper(ctx);
		PublicMessage msg = doPubMsgBuild(wrapper);
		wrapper.setBuildedMsg(msg);
		this.doPubMsgRelatedDataBuild(wrapper);
		this.doFileResourceBuild(wrapper);
		return msg;

	}

	protected void doFileResourceBuild(PubMsgBuildContextWrapper ctx)
			throws IOException, ImageScaleException {
		PubMsgFileProcessor processor = new PubMsgFileProcessor(ctx);
		processor.processDisplayPic();
		processor.processRecognPic();
	}

	/**
	 * 创建原创消息
	 * 
	 * @param content
	 * @param t
	 * @param dto
	 * @return
	 */
	protected PublicMessage doPubMsgBuild(PubMsgBuildContextWrapper ctx) {
		PublicMessage message = new PublicMessage();
		message.setCreatorId(ctx.getCreatorUserId());
		message.setMsgStatus(MsgStatus.publicMsg);
		message.setRecognizePicUrl(ctx.getRecognPicUrl());
		message.setDisplayPicUrl(ctx.getDisplayPicUrl());
		message.setPublishTime(new Date());
		message.setSceneId(ctx.getSceneId());
		message.setMsgStatus(MsgStatus.publicMsg);
		pubMsgDAO.save(message);
		return message;
	}

	protected void doPubMsgRelatedDataBuild(PubMsgBuildContextWrapper ctx) {
		PubMsgRelatedDataProcessor processor = new PubMsgRelatedDataProcessor(ctx);
		processor.doPubMsgIndexBuild();
		processor.doPubMsgStatisticRecordBuild();
	}
	
	

	class PubMsgRelatedDataProcessor {

		private final PubMsgBuildContextWrapper ctx;

		public PubMsgRelatedDataProcessor(PubMsgBuildContextWrapper ctx) {
			this.ctx = ctx;
		}

		private PubMsgStatisticRecorder doPubMsgStatisticRecordBuild() {
			PubMsgStatisticRecorder r = new PubMsgStatisticRecorder();
			r.setMessageId(ctx.getBuildedMsg().getId());
			r.setPraiseNum(0);
			r = msgRecorderDAO.save(r);
			return r;
		}

		private void doPubMsgIndexBuild() {
			publicMessageIndexDAO.addPublicMsgIndex(new PublicMessageIndex(ctx
					.getBuildedMsg().getId(), ctx.getCreatorUserId(), ctx
					.getDisplayPicUrl(), MsgStatus.publicMsg,new Date()));
		}

	}

	class PubMsgFileProcessor {

		private final PubMsgBuildContextWrapper ctx;

		public PubMsgFileProcessor(PubMsgBuildContextWrapper ctx) {
			this.ctx = ctx;
		}

		protected void processDisplayPic() throws IOException,
				ImageScaleException {
			if (ctx.getDisplayPicFileEntity() != null) {
				ctx.getDisplayPicFileEntity().save();
				scaleService.scaleImage(new RatioImageScaleContext(ctx
						.getDisplayPicFileEntity().getFile()));
			}
		}

		protected void processRecognPic() throws IOException {
			if (ctx.getRecognPicFileEntity() != null) {
				ctx.getRecognPicFileEntity().save();
			}
		}
	}

	protected class PubMsgBuildContextWrapper extends PubMsgBuildContext {

		private FileEntity displayPicFileEntity;

		private FileEntity recognPicFileEntity;

		private PublicMessage buildedMsg;

		public PubMsgBuildContextWrapper(PubMsgBuildContext ctx) {
			super(ctx);
			if (ctx.getDisplayPicEntity() != null) {
				this.displayPicFileEntity = fileLocatorManager
						.getDisplayPicFileLocator().getNewFileEntity(
								new FileLocationConfig(ctx
										.getDisplayPicEntity(), 2));
			}
			if (ctx.getRecognPicEntity() != null) {
				this.recognPicFileEntity = fileLocatorManager
						.getRecognPicFileLocator().getNewFileEntity(
								new FileLocationConfig(
										ctx.getRecognPicEntity(), 2));
			}
		}

		public String getDisplayPicUrl() {
			return displayPicFileEntity == null ? null : displayPicFileEntity
					.getFilePathExcludeRoot();
		}

		public String getRecognPicUrl() {
			return recognPicFileEntity == null ? null : recognPicFileEntity
					.getFilePathExcludeRoot();
		}

		public FileEntity getDisplayPicFileEntity() {
			return displayPicFileEntity;
		}

		public FileEntity getRecognPicFileEntity() {
			return recognPicFileEntity;
		}

		public PublicMessage getBuildedMsg() {
			return buildedMsg;
		}

		public void setBuildedMsg(PublicMessage buildedMsg) {
			this.buildedMsg = buildedMsg;
		}

	}

	public static class PubMsgBuildContext {

		private final InputStream displayPicEntity;

		private final InputStream recognPicEntity;

		private final Long sceneId;

		private final Long creatorUserId;

		public PubMsgBuildContext(InputStream displayPicEntity,
				InputStream recognEntity, Long sceneId, Long creatorUserId) {
			this.displayPicEntity = displayPicEntity;
			this.sceneId = sceneId;
			this.creatorUserId = creatorUserId;
			this.recognPicEntity = recognEntity;
		}

		public PubMsgBuildContext(PubMsgBuildContext ctx) {
			this.displayPicEntity = ctx.getDisplayPicEntity();
			this.creatorUserId = ctx.getCreatorUserId();
			this.sceneId = ctx.getSceneId();
			this.recognPicEntity = ctx.getRecognPicEntity();
		}

		public InputStream getDisplayPicEntity() {
			return displayPicEntity;
		}

		public Long getSceneId() {
			return sceneId;
		}

		public Long getCreatorUserId() {
			return creatorUserId;
		}

		public InputStream getRecognPicEntity() {
			return recognPicEntity;
		}

	}
}
